package zy.service.money.stream.impl;

import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import zy.dao.approve.ApproveRecordDAO;
import zy.dao.base.stream.StreamBillDAO;
import zy.dao.base.stream.StreamDAO;
import zy.dao.money.bank.BankDAO;
import zy.dao.money.bank.BankRunDAO;
import zy.dao.money.stream.StreamSettleDAO;
import zy.entity.PageData;
import zy.entity.PageInfo;
import zy.entity.approve.T_Approve_Record;
import zy.entity.base.stream.T_Base_Stream;
import zy.entity.base.stream.T_Base_Stream_Bill;
import zy.entity.money.bank.T_Money_Bank;
import zy.entity.money.bank.T_Money_BankRun;
import zy.entity.money.stream.T_Money_StreamSettle;
import zy.entity.money.stream.T_Money_StreamSettleList;
import zy.entity.sys.user.T_Sys_User;
import zy.service.money.stream.StreamSettleService;
import zy.util.CommonUtil;
import zy.util.DateUtil;
import zy.util.StringUtil;

@Service
public class StreamSettleServiceImpl implements StreamSettleService{
	@Resource
	private StreamSettleDAO streamSettleDAO;
	@Resource
	private ApproveRecordDAO approveRecordDAO;
	@Resource
	private BankDAO bankDAO;
	@Resource
	private BankRunDAO bankRunDAO;
	@Resource
	private StreamDAO streamDAO;
	@Resource
	private StreamBillDAO streamBillDAO;
	
	@Override
	public PageData<T_Money_StreamSettle> page(Map<String, Object> params) {
		Integer pageSize = (Integer)params.get(CommonUtil.PAGESIZE);
		Integer pageIndex = (Integer)params.get(CommonUtil.PAGEINDEX);
		
		Integer totalCount = streamSettleDAO.count(params);
		PageInfo pageInfo = new PageInfo(totalCount, pageSize, pageIndex);
		params.put(CommonUtil.START, (pageIndex-1)*pageSize);
		params.put(CommonUtil.END, pageSize);
		
		List<T_Money_StreamSettle> list = streamSettleDAO.list(params);
		PageData<T_Money_StreamSettle> pageData = new PageData<T_Money_StreamSettle>();
		pageData.setPageInfo(pageInfo);
		pageData.setList(list);
		return pageData;
	}
	
	@Override
	public PageData<T_Base_Stream_Bill> pageBill(Map<String, Object> params) {
		Integer pageSize = (Integer)params.get(CommonUtil.PAGESIZE);
		Integer pageIndex = (Integer)params.get(CommonUtil.PAGEINDEX);
		
		Integer totalCount = streamBillDAO.count(params);
		PageInfo pageInfo = new PageInfo(totalCount, pageSize, pageIndex);
		params.put(CommonUtil.START, (pageIndex-1)*pageSize);
		params.put(CommonUtil.END, pageSize);
		
		List<T_Base_Stream_Bill> list = streamBillDAO.list(params);
		PageData<T_Base_Stream_Bill> pageData = new PageData<T_Base_Stream_Bill>();
		pageData.setPageInfo(pageInfo);
		pageData.setList(list);
		return pageData;
	}
	
	@Override
	public T_Money_StreamSettle load(Integer st_id) {
		T_Money_StreamSettle settle = streamSettleDAO.load(st_id);
		if(settle != null){
			T_Approve_Record approve_Record = approveRecordDAO.load(settle.getSt_number(), settle.getCompanyid());
			if(approve_Record != null){
				settle.setAr_describe(approve_Record.getAr_describe());
			}
		}
		return settle;
	}
	
	@Override
	public T_Money_StreamSettle load(String number, Integer companyid) {
		return streamSettleDAO.load(number, companyid);
	}
	
	@Override
	public T_Base_Stream loadStream(String se_code,Integer companyid) {
		return streamDAO.loadStream(se_code, companyid);
	}
	
	@Override
	public List<T_Money_StreamSettleList> temp_list(Map<String, Object> params) {
		return streamSettleDAO.temp_list(params);
	}

	@Override
	@Transactional
	public void temp_save(String se_code, T_Sys_User user) {
		if (StringUtil.isEmpty(se_code)) {
			throw new RuntimeException("请选择物流公司");
		}
		T_Money_StreamSettle existSettle = streamSettleDAO.check_settle(se_code, user.getCompanyid());
		if(existSettle != null){
			throw new RuntimeException("该物流公司有单据未审核，不能再结算!");
		}
		streamSettleDAO.temp_clear(user.getUs_id(), user.getCompanyid());
		List<T_Money_StreamSettleList> temps = streamSettleDAO.load_bill_forsavetemp(se_code, user.getCompanyid());
		for (T_Money_StreamSettleList temp : temps) {
			temp.setStl_us_id(user.getUs_id());
			temp.setCompanyid(user.getCompanyid());
		}
		streamSettleDAO.temp_save(temps);
	}
	
	@Override
	@Transactional
	public void temp_updateDiscountMoney(T_Money_StreamSettleList temp) {
		streamSettleDAO.temp_updateDiscountMoney(temp);
	}

	@Override
	@Transactional
	public void temp_updateRealMoney(T_Money_StreamSettleList temp) {
		streamSettleDAO.temp_updateRealMoney(temp);
	}

	@Override
	@Transactional
	public void temp_updateRemark(T_Money_StreamSettleList temp) {
		streamSettleDAO.temp_updateRemark(temp);
	}

	@Override
	@Transactional
	public void temp_entire(Map<String, Object> params) {
		Double discount_money = (Double)params.get("discount_money");
		Double paid = (Double)params.get("paid");
		T_Sys_User user = (T_Sys_User)params.get("user");
		if(discount_money == null || paid == null){
			throw new RuntimeException("整单结算金额不能为空");
		}
		if (discount_money.doubleValue() == 0d && paid.doubleValue() == 0d) {
			throw new RuntimeException("整单结算金额不能为0");
		}
		params.put("stl_us_id", user.getUs_id());
		params.put("companyid", user.getCompanyid());
		List<T_Money_StreamSettleList> temps = streamSettleDAO.temp_list(params);
		
		double remained_discount_money = discount_money;
		double remained_paid = paid;
		for (T_Money_StreamSettleList temp : temps) {
			
			Double temp_discount_money = null;
			Double temp_paid = null;
			
			// 使用优惠金额
			if (remained_discount_money > 0) {
				temp_discount_money = Math.min(remained_discount_money,temp.getStl_unpayable());
				remained_discount_money -= temp_discount_money;
			}else{
				temp_discount_money = 0d;
			}
			temp.setStl_discount_money(temp_discount_money);//设置本次使用优惠金额
			
			//使用实付金额
			if(remained_paid > 0){
				temp_paid = Math.min(remained_paid, temp.getStl_unpayable()-temp.getStl_discount_money());
				remained_paid -= temp_paid;
			}else{
				temp_paid = 0d;
			}
			temp.setStl_real_pay(temp_paid);
		}
		streamSettleDAO.temp_update(temps);
	}

	@Override
	public List<T_Money_StreamSettleList> detail_list(String number,Integer companyid) {
		return streamSettleDAO.detail_list(number, companyid);
	}
	
	@Override
	@Transactional
	public void save(T_Money_StreamSettle settle, T_Sys_User user) {
		if(settle == null){
			throw new IllegalArgumentException("参数不能为null");
		}
		if(StringUtil.isEmpty(settle.getSt_stream_code())){
			throw new IllegalArgumentException("物流公司不能为空");
		}
		if(StringUtil.isEmpty(settle.getSt_ba_code())){
			throw new IllegalArgumentException("银行账户不能为空");
		}
		if(StringUtil.isEmpty(settle.getSt_manager())){
			throw new IllegalArgumentException("经办人不能为空");
		}
		settle.setCompanyid(user.getCompanyid());
		settle.setSt_us_id(user.getUs_id());
		settle.setSt_maker(user.getUs_name());
		settle.setSt_ar_state(CommonUtil.AR_STATE_NOTAPPROVE);
		settle.setSt_sysdate(DateUtil.getCurrentTime());
		//1.查临时表
		List<T_Money_StreamSettleList> temps = streamSettleDAO.temp_list_forsave(user.getUs_id(),user.getCompanyid());
		if(temps == null || temps.size() == 0){
			throw new RuntimeException("单据已保存，请勿重复提交");
		}
		//2.保存单据
		double st_discount_money = 0d;
		double st_paid = 0d;
		for (T_Money_StreamSettleList temp : temps) {
			st_discount_money += temp.getStl_discount_money();
			st_paid += temp.getStl_real_pay();
		}
		settle.setSt_discount_money(st_discount_money);
		settle.setSt_paid(st_paid);
		
		streamSettleDAO.save(settle, temps);
		//3.删除临时表
		streamSettleDAO.temp_clear(user.getUs_id(), user.getCompanyid());
	}
	
	@Override
	@Transactional
	public void update(T_Money_StreamSettle settle, T_Sys_User user) {
		if(settle == null){
			throw new IllegalArgumentException("参数不能为null");
		}
		if(StringUtil.isEmpty(settle.getSt_stream_code())){
			throw new IllegalArgumentException("物流公司不能为空");
		}
		if(StringUtil.isEmpty(settle.getSt_ba_code())){
			throw new IllegalArgumentException("银行账户不能为空");
		}
		if(StringUtil.isEmpty(settle.getSt_manager())){
			throw new IllegalArgumentException("经办人不能为空");
		}
		
		settle.setCompanyid(user.getCompanyid());
		settle.setSt_us_id(user.getUs_id());
		settle.setSt_maker(user.getUs_name());
		settle.setSt_ar_state(CommonUtil.AR_STATE_NOTAPPROVE);
		settle.setSt_ar_date(null);
		settle.setSt_sysdate(DateUtil.getCurrentTime());
		//1.1查临时表
		List<T_Money_StreamSettleList> temps = streamSettleDAO.temp_list_forsave(user.getUs_id(),user.getCompanyid());
		if(temps == null || temps.size() == 0){
			throw new RuntimeException("单据已保存，请勿重复提交");
		}
		//1.2验证单据
		T_Money_StreamSettle oldSettle = streamSettleDAO.check(settle.getSt_number(), user.getCompanyid());
		if (oldSettle == null || !CommonUtil.AR_STATE_FAIL.equals(oldSettle.getSt_ar_state())) {
			throw new RuntimeException("单据已修改，请勿重复提交");
		}
		//2.保存单据
		double st_discount_money = 0d;
		double st_paid = 0d;
		for (T_Money_StreamSettleList temp : temps) {
			st_discount_money += temp.getStl_discount_money();
			st_paid += temp.getStl_real_pay();
		}
		settle.setSt_discount_money(st_discount_money);
		settle.setSt_paid(st_paid);
		streamSettleDAO.deleteList(settle.getSt_number(), user.getCompanyid());
		streamSettleDAO.update(settle, temps);
		//3.删除临时表
		streamSettleDAO.temp_clear(user.getUs_id(), user.getCompanyid());
	}
	
	@Override
	@Transactional
	public T_Money_StreamSettle approve(String number, T_Approve_Record record, T_Sys_User user) {
		if (number == null) {
			throw new IllegalArgumentException("参数number不能为null");
		}
		T_Money_StreamSettle settle = streamSettleDAO.check(number, user.getCompanyid());
		if(settle == null){
			throw new RuntimeException("单据不存在");
		}
		if(!CommonUtil.AR_STATE_NOTAPPROVE.equals(settle.getSt_ar_state())){
			throw new RuntimeException("单据已经审核");
		}
		//更新单据审核状态
		settle.setSt_ar_state(record.getAr_state());
		settle.setSt_ar_date(DateUtil.getCurrentTime());
		streamSettleDAO.updateApprove(settle);
		//保存审核记录表
		record.setAr_number(number);
		record.setAr_sysdate(DateUtil.getCurrentTime());
		record.setAr_us_name(user.getUs_name());
		record.setAr_type("t_money_streamsettle");
		record.setCompanyid(user.getCompanyid());
		approveRecordDAO.save(record);
		if(!CommonUtil.AR_STATE_APPROVED.equals(settle.getSt_ar_state())){//审核不通过，则直接返回
			return settle;
		}
		//3.审核通过
		//3.1更新财务
		T_Base_Stream stream = streamDAO.loadStream(settle.getSt_stream_code(), user.getCompanyid());
		stream.setSe_payable(stream.getSe_payable()-settle.getSt_discount_money());
		stream.setSe_payabled(stream.getSe_payabled()+settle.getSt_paid());
		streamDAO.updateSettle(stream);
		
		//更改物流单金额数据
		List<T_Base_Stream_Bill> bills = streamSettleDAO.listBillBySettle(number, user.getCompanyid());
		if (bills.size() > 0) {
			for (T_Base_Stream_Bill bill : bills) {
				double sum = Math.abs(bill.getSeb_discount_money()+bill.getSeb_payabled());
				if (sum == 0) {
					bill.setSeb_pay_state(CommonUtil.PAY_STATE_UNPAY);
				} else if (sum < Math.abs(bill.getSeb_money())) {
					bill.setSeb_pay_state(CommonUtil.PAY_STATE_PART);
				} else {
					bill.setSeb_pay_state(CommonUtil.PAY_STATE_FINISH);
				}
			}
			streamSettleDAO.updateBillBySettle(bills);
		}
		
		if(settle.getSt_paid() != 0){//更改银行帐户余额
			T_Money_Bank bank = bankDAO.queryByCode(settle.getSt_ba_code(), user.getCompanyid());
			bank.setBa_balance(bank.getBa_balance()-settle.getSt_paid());
			bankDAO.updateBalanceById(bank);
			if(settle.getSt_paid() != 0){//银行流水账
				T_Money_BankRun bankRun = new T_Money_BankRun();
				bankRun.setBr_ba_code(settle.getSt_ba_code());
				bankRun.setBr_balance(bank.getBa_balance());
				bankRun.setBr_bt_code(CommonUtil.BANKRUN_STREAMSETTLE);
				bankRun.setBr_date(DateUtil.getCurrentTime());
				if(settle.getSt_paid()>0){
					bankRun.setBr_out(Math.abs(settle.getSt_paid()));
				}else {
					bankRun.setBr_enter(Math.abs(settle.getSt_paid()));
				}
				bankRun.setBr_manager(settle.getSt_manager());
				bankRun.setBr_number(number);
				bankRun.setBr_remark("物流结算单");
				bankRun.setBr_shop_code(bank.getBa_shop_code());
				bankRun.setBr_sysdate(DateUtil.getCurrentTime());
				bankRun.setCompanyid(user.getCompanyid());
				bankRunDAO.save(bankRun);
			}
		}
		
		return settle;
	}
	
	@Override
	@Transactional
	public T_Money_StreamSettle reverse(String number, T_Sys_User user) {
		if (number == null) {
			throw new IllegalArgumentException("参数number不能为null");
		}
		T_Money_StreamSettle settle = streamSettleDAO.check(number, user.getCompanyid());
		if(settle == null){
			throw new RuntimeException("单据不存在");
		}
		if(!CommonUtil.AR_STATE_APPROVED.equals(settle.getSt_ar_state())){
			throw new RuntimeException("单据未审核或审核未通过");
		}
		//1.更新单据审核状态
		settle.setSt_ar_state(CommonUtil.AR_STATE_NOTAPPROVE);
		settle.setSt_ar_date(DateUtil.getCurrentTime());
		streamSettleDAO.updateApprove(settle);
		//2.保存审核记录表
		T_Approve_Record record = new T_Approve_Record();
		record.setAr_state(CommonUtil.AR_STATE_REVERSE_APPROVE);
		record.setAr_describe(user.getUs_name()+"反审核单据");
		record.setAr_number(number);
		record.setAr_sysdate(DateUtil.getCurrentTime());
		record.setAr_us_name(user.getUs_name());
		record.setAr_type("t_money_streamsettle");
		record.setCompanyid(user.getCompanyid());
		approveRecordDAO.save(record);
		
		//3更新财务
		T_Base_Stream stream = streamDAO.loadStream(settle.getSt_stream_code(), user.getCompanyid());
		stream.setSe_payable(stream.getSe_payable()+settle.getSt_discount_money());
		stream.setSe_payabled(stream.getSe_payabled()-settle.getSt_paid());
		streamDAO.updateSettle(stream);
		//更改物流单金额数据
		List<T_Base_Stream_Bill> bills = streamSettleDAO.listBillBySettle_Reverse(number, user.getCompanyid());
		if (bills.size() > 0) {
			for (T_Base_Stream_Bill bill : bills) {
				double sum = Math.abs(bill.getSeb_discount_money()+bill.getSeb_payabled());
				if (sum == 0) {
					bill.setSeb_pay_state(CommonUtil.PAY_STATE_UNPAY);
				} else if (sum < Math.abs(bill.getSeb_money())) {
					bill.setSeb_pay_state(CommonUtil.PAY_STATE_PART);
				} else {
					bill.setSeb_pay_state(CommonUtil.PAY_STATE_FINISH);
				}
			}
			streamSettleDAO.updateBillBySettle(bills);
		}
		if(settle.getSt_paid() != 0){//更改银行帐户余额
			T_Money_Bank bank = bankDAO.queryByCode(settle.getSt_ba_code(), user.getCompanyid());
			bank.setBa_balance(bank.getBa_balance()+settle.getSt_paid());
			bankDAO.updateBalanceById(bank);
			if(settle.getSt_paid() != 0){//供应商结算单银行流水账
				T_Money_BankRun bankRun = new T_Money_BankRun();
				bankRun.setBr_ba_code(settle.getSt_ba_code());
				bankRun.setBr_balance(bank.getBa_balance());
				bankRun.setBr_bt_code(CommonUtil.BANKRUN_STREAMSETTLE);
				bankRun.setBr_date(DateUtil.getCurrentTime());
				if(settle.getSt_paid()>0){
					bankRun.setBr_enter(Math.abs(settle.getSt_paid()));
				}else {
					bankRun.setBr_out(Math.abs(settle.getSt_paid()));
				}
				bankRun.setBr_manager(settle.getSt_manager());
				bankRun.setBr_number(number);
				bankRun.setBr_remark("反审核恢复账目");
				bankRun.setBr_shop_code(bank.getBa_shop_code());
				bankRun.setBr_sysdate(DateUtil.getCurrentTime());
				bankRun.setCompanyid(user.getCompanyid());
				bankRunDAO.save(bankRun);
			}
		}
		return settle;
	}
	
	@Override
	@Transactional
	public void initUpdate(String number, Integer us_id, Integer companyid) {
		List<T_Money_StreamSettleList> details = streamSettleDAO.detail_list(number, companyid);
		for(T_Money_StreamSettleList item:details){
			item.setStl_us_id(us_id);
		}
		streamSettleDAO.temp_clear(us_id, companyid);
		streamSettleDAO.temp_save(details);
	}
	
	@Override
	@Transactional
	public void del(String number, Integer companyid) {
		if (number == null) {
			throw new IllegalArgumentException("参数number不能为null");
		}
		T_Money_StreamSettle settle = streamSettleDAO.check(number, companyid);
		if(settle == null){
			throw new RuntimeException("单据不存在");
		}
		if(!CommonUtil.AR_STATE_NOTAPPROVE.equals(settle.getSt_ar_state()) && !CommonUtil.AR_STATE_FAIL.equals(settle.getSt_ar_state())){
			throw new RuntimeException("单据已审核通过不能删除！");
		}
		streamSettleDAO.del(number, companyid);
	}
	
}
